子宫颈图片反光部分的自动检测


  • 反光部分的分割
    • 准确度
    • 召回率

  • 反光部分的填充

目录


  • 一些文章里的算法的分析和实现

  • 最终采用的算法

多阶段的分割算法

  • Intensity $I = \frac{R + G + B}{3}$ Saturation $S = 1 - \frac{\min(R,G,B)}{I} $ $$ I > 0.4 * I_{max}\ \ and\ \ S < 0.6 * S_{max} $$
  • gradient magnitude $ |\triangledown G| = \sqrt{(\frac{\partial I}{\partial x})^2 + (\frac{\partial I}{\partial y})^2}$ $$ |\triangledown G| > 0.15 $$
  • Gaussin Mixture Model cluster 概率密度函数 $$ p(x_{i}) = \sum_{k=1}^{K}\pi_{k}P(x_i|j) \\ = \sum_{k=1}^{K}\pi_{k} \mathcal{N}(x_i|\mu_k,\Sigma_k) $$
    • S -- V feature space, where S and V are Saturation and Value of the standard HSV color space
  • 似然函数: $$ \prod_{i=1}^{N}p(x_i) $$
  • log似然函数: $$ \sum_{i=1}^{N}\log p(x_i) = \sum_{i=1}^{N}\log (\sum_{k=1}^{K}\pi_{k} \mathcal{N}(x_i|\mu_k,\Sigma_k)) $$
  • EM算法:引入因变量z,似然函数变为:$$\prod_{i=1}^{N}p(x_i,z_i) = \prod_{i=1}^{N}p(z_i)p(x_i|z_i) = \prod_{i=1}^{N} \prod_{k=1}^{K}(\pi_k)^{z_k}\mathcal{N}(x_i|\mu_k,\Sigma_k)^{z_k}$$
  • log似然:$$\sum_{i=1}^{N}\sum_{i=1}^{N}z_{ik}\{\log \pi_k + \log \mathcal{N}(x_i|\mu_k,\Sigma_k)\}$$
  • 估计$z_k$,根据后验概率取期望:$$z_k = 0 * p(z_k = 0|x) + 1 * p(z_k = 1 | x) \\ = p(z_k = 1 | x) \\= \frac{p(x)p(x|z_k =1)}{p(z_k)} \\= \frac{\pi_k\mathcal{N}(x|\mu_k,\Sigma_k)}{\sum_{j=1}^{K}\pi_j\mathcal{N}(x|\mu_j,\Sigma_j)}$$

填充算法

In [10]:
plt.figure(figsize=(40,40))
plt.subplot(1,2,1)
plt.imshow(image)
plt.title("Image")
plt.subplot(1,2,2)
plt.imshow(test1)
plt.title("after Intensity and Saturation selection")
Out[10]:
<matplotlib.text.Text at 0x7fe96b5d9c50>
In [12]:
plt.figure(figsize=(40,40))
plt.subplot(1,2,1)
plt.imshow(test2)
plt.title("after gradient magtitude selection")
plt.subplot(1,2,2)
plt.imshow(test3)
plt.title("after GMM")
Out[12]:
<matplotlib.text.Text at 0x7fe96b3b49b0>
In [13]:
plt.figure(figsize=(10,10))
# plt.subplot(1,2,1)
plt.imshow(test4)
plt.title("after fill process")
Out[13]:
<matplotlib.text.Text at 0x7fe969383c18>

第二种分割算法

  • stage1:
    • $c_E = 0.2989 · c_R + 0.5870·c_G + 0.1140·c_B$
    • $r_{GE} = \frac{P_{95}(c_{G})}{P_{95}(c_E)}$ $r_{BE} = \frac{P_{95}(c_{B})}{P_{95}(c_E)}$
    • $c_{G}(x_0) > r_{GE} * T_1 \mid c_{B}(x_0) > r_{BE} * T_1 \mid c_E(x_0) > T_1 $
  • stage2:
    • $\varepsilon(x_0) = \max \{ \frac{c_R(x_0)}{c^*_R(x_0)},\frac{c_G(x_0)}{c^*_G(x_0)},\frac{c_B(x_0)}{c^*_B(x_0)} \} $
    • $c^*(x) 是一个经过填充,滤波后的图片$
    • $\varepsilon(x) > T_2$
  • stage3:
    • $\frac{1}{N}\sum_{i=1}{N}|grad(E_n)| > T_3 \land N > N_{min}$

比较好的方法

  • 算法要有很好的鲁棒性,不能在一张图片上过拟合
  • 思想就是既要考虑召回率又要考虑准确度,加一点,减一点
  • 算法要考虑到数据本身的实际情况,不能简单的拿来套用,比如要考虑消除图片上的tag,图片反光的特征

stage1: 根据每一个像素点的variance,选出反光部分的一个尽可能大的真子集

stage2: 为了消除边界部分反光的点,防止填充的时候影响效果,把上一步的mask矩阵进行一个扩充

stage3: 进行第一次填充

stage4: 上一步填充完还是有一些孤立的反光点没有被消除,所以把上一步的填充做一个中值滤波,利用第二篇文章的思想,用滤波后的照片作填充,作为最后的结果

In [15]:
plt.figure(figsize=(8,8))
plt.imshow(paint_2)
plt.title("after var remove and fill")
Out[15]:
<matplotlib.image.AxesImage at 0x7effaf738ac8>
In [215]:
plt.figure(figsize=(8,8))
plt.imshow(paint_4)
plt.title("after background fillprocess")
Out[215]:
<matplotlib.image.AxesImage at 0x7f0e1eb84320>
In [52]:
def show(k ) :
    _, basename = os.path.split(showfile[k])
    resoult = "./output/show/" + basename
    plt.figure(figsize=(40,40))
    plt.subplot(1,2,1)
    plt.imshow(Image.open(showfile[k]))
    plt.subplot(1,2,2)
    plt.imshow(Image.open(resoult))
In [56]:
 show(1)
In [57]:
show(2)
In [58]:
show(3)
In [79]:
show(4)
In [80]:
show(5)
In [62]:
show(9)
In [64]:
show(np.random.randint(1)%80)
In [72]:
show(np.random.randint(80))
In [78]:
show(np.random.randint(80))

🔚